home *** CD-ROM | disk | FTP | other *** search
/ Experimental BBS Explossion 3 / Experimental BBS Explossion III.iso / games / nhak_src.zip / UNIXMAIN.C < prev    next >
C/C++ Source or Header  |  1993-03-16  |  11KB  |  469 lines

  1. /*    SCCS Id: @(#)unixmain.c    3.0    89/01/13
  2. /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
  3. /* NetHack may be freely redistributed.  See license for details. */
  4. /* main.c - Unix NetHack */
  5.  
  6. #include "hack.h"
  7.  
  8. #include <signal.h>
  9. #include <pwd.h>
  10. #ifndef O_RDONLY
  11. #include <fcntl.h>
  12. #endif
  13.  
  14. char SAVEF[PL_NSIZ + 11] = "save/";    /* save/99999player */
  15.  
  16. const char *hname = 0;        /* name of the game (argv[0] of call) */
  17. char obuf[BUFSIZ];    /* BUFSIZ is defined in stdio.h */
  18. int hackpid = 0;                /* current pid */
  19. int locknum = 0;                /* max num of players */
  20. #ifdef DEF_PAGER
  21. char *catmore = 0;                /* default pager */
  22. #endif
  23.  
  24. extern struct passwd *getpwnam(), *getpwuid();
  25. #ifdef CHDIR
  26. static void chdirx();
  27. #endif /* CHDIR */
  28. static void whoami();
  29.  
  30. int
  31. main(argc,argv)
  32. int argc;
  33. char *argv[];
  34. {
  35.     extern int x_maze_max, y_maze_max;
  36.     register int fd;
  37. #ifdef CHDIR
  38.     register char *dir;
  39. #endif
  40. #ifdef COMPRESS
  41.     char    cmd[80], old[80];
  42. #endif
  43.  
  44.     hname = argv[0];
  45.     hackpid = getpid();
  46.     (void) umask(0);
  47.  
  48.     /*
  49.      *  Remember tty modes, to be restored on exit.
  50.      *
  51.      *  gettty() must be called before startup()
  52.      *    due to ordering of LI/CO settings
  53.      *  startup() must be called before initoptions()
  54.      *    due to ordering of graphics settings
  55.      */
  56.     gettty();
  57.     setbuf(stdout,obuf);
  58.     startup();
  59.     initoptions();
  60.     whoami();
  61.  
  62. #ifdef CHDIR            /* otherwise no chdir() */
  63.     /*
  64.      * See if we must change directory to the playground.
  65.      * (Perhaps hack runs suid and playground is inaccessible
  66.      *  for the player.)
  67.      * The environment variable HACKDIR is overridden by a
  68.      *  -d command line option (must be the first option given)
  69.      */
  70.     dir = getenv("HACKDIR");
  71. #endif
  72.     if(argc > 1) {
  73. #ifdef CHDIR
  74.         if (!strncmp(argv[1], "-d", 2) && argv[1][2] != 'e') {
  75.         /* avoid matching "-dec" for DECgraphics; since the man page
  76.          * says -d directory, hope nobody's using -desomething_else
  77.          */
  78.         argc--;
  79.         argv++;
  80.         dir = argv[0]+2;
  81.         if(*dir == '=' || *dir == ':') dir++;
  82.         if(!*dir && argc > 1) {
  83.             argc--;
  84.             argv++;
  85.             dir = argv[0];
  86.         }
  87.         if(!*dir)
  88.             error("Flag -d must be followed by a directory name.");
  89.         } else
  90. #endif /* CHDIR /**/
  91.  
  92.     /*
  93.      * Now we know the directory containing 'record' and
  94.      * may do a prscore().
  95.      */
  96.         if (!strncmp(argv[1], "-s", 2)) {
  97. #ifdef CHDIR
  98.         chdirx(dir,0);
  99. #endif
  100.         prscore(argc, argv);
  101.         if(isatty(1)) getret();
  102.         settty(NULL);
  103.         exit(0);
  104.         }
  105.     }
  106.  
  107.     /*
  108.      * It seems you really want to play.
  109.      */
  110.     setrandom();
  111.     cls();
  112.     u.uhp = 1;    /* prevent RIP on early quits */
  113.     u.ux = FAR;    /* prevent nscr() */
  114.     (void) signal(SIGHUP, (SIG_RET_TYPE) hangup);
  115. #ifdef SIGXCPU
  116.     (void) signal(SIGXCPU, (SIG_RET_TYPE) hangup);
  117. #endif
  118.  
  119.     /*
  120.      * Find the creation date of this game,
  121.      * so as to avoid restoring outdated savefiles.
  122.      */
  123.     gethdate(hname);
  124.  
  125.     /*
  126.      * We cannot do chdir earlier, otherwise gethdate will fail.
  127.      */
  128. #ifdef CHDIR
  129.     chdirx(dir,1);
  130. #endif
  131.  
  132.     /*
  133.      * Process options.
  134.      */
  135.     while(argc > 1 && argv[1][0] == '-'){
  136.         argv++;
  137.         argc--;
  138.         switch(argv[0][1]){
  139. #if defined(WIZARD) || defined(EXPLORE_MODE)
  140. # ifndef EXPLORE_MODE
  141.         case 'X':
  142. # endif
  143.         case 'D':
  144. # ifdef WIZARD
  145.             {
  146.               char *user;
  147.               int uid;
  148.               struct passwd *pw = (struct passwd *)0;
  149.  
  150.               uid = getuid();
  151.               user = getlogin();
  152.               if (user) {
  153.                   pw = getpwnam(user);
  154.                   if (pw && (pw->pw_uid != uid)) pw = 0;
  155.               }
  156.               if (pw == 0) {
  157.                   user = getenv("USER");
  158.                   if (user) {
  159.                   pw = getpwnam(user);
  160.                   if (pw && (pw->pw_uid != uid)) pw = 0;
  161.                   }
  162.                   if (pw == 0) {
  163.                   pw = getpwuid(uid);
  164.                   }
  165.               }
  166.               if (pw && !strcmp(pw->pw_name,WIZARD)) {
  167.                   wizard = TRUE;
  168.                   break;
  169.               }
  170.             }
  171.             /* otherwise fall thru to discover */
  172. # endif
  173. # ifdef EXPLORE_MODE
  174.         case 'X':
  175.             discover = TRUE;
  176. # endif
  177.             break;
  178. #endif
  179. #ifdef NEWS
  180.         case 'n':
  181.             flags.nonews = TRUE;
  182.             break;
  183. #endif
  184.         case 'u':
  185.             if(argv[0][2])
  186.               (void) strncpy(plname, argv[0]+2, sizeof(plname)-1);
  187.             else if(argc > 1) {
  188.               argc--;
  189.               argv++;
  190.               (void) strncpy(plname, argv[0], sizeof(plname)-1);
  191.             } else
  192.                 Printf("Player name expected after -u\n");
  193.             break;
  194.         case 'i':
  195.             if(!strcmp(argv[0]+1, "ibm")) assign_ibm_graphics();
  196.             break;
  197.         case 'd':
  198.             if(!strcmp(argv[0]+1, "dec")) assign_dec_graphics();
  199.             break;
  200.         default:
  201.             /* allow -T for Tourist, etc. */
  202.             (void) strncpy(pl_character, argv[0]+1,
  203.                 sizeof(pl_character)-1);
  204.  
  205.             /* Printf("Unknown option: %s\n", *argv); */
  206.         }
  207.     }
  208.  
  209.     if(argc > 1)
  210.         locknum = atoi(argv[1]);
  211. #ifdef MAX_NR_OF_PLAYERS
  212.     if(!locknum || locknum > MAX_NR_OF_PLAYERS)
  213.         locknum = MAX_NR_OF_PLAYERS;
  214. #endif
  215. #ifdef DEF_PAGER
  216.     if(!(catmore = getenv("HACKPAGER")) && !(catmore = getenv("PAGER")))
  217.         catmore = DEF_PAGER;
  218. #endif
  219. #ifdef MAIL
  220.     getmailstatus();
  221. #endif
  222. #ifdef WIZARD
  223.     if (wizard)
  224.         Strcpy(plname, "wizard");
  225.     else
  226. #endif
  227.     if(!*plname || !strncmp(plname, "player", 4)
  228.             || !strncmp(plname, "games", 4))
  229.         askname();
  230.     plnamesuffix();        /* strip suffix from name; calls askname() */
  231.                 /* again if suffix was whole name */
  232.                 /* accepts any suffix */
  233. #ifdef WIZARD
  234.     if(!wizard) {
  235. #endif
  236.         /*
  237.          * check for multiple games under the same name
  238.          * (if !locknum) or check max nr of players (otherwise)
  239.          */
  240.         (void) signal(SIGQUIT,SIG_IGN);
  241.         (void) signal(SIGINT,SIG_IGN);
  242.         if(!locknum)
  243.             Sprintf(lock, "%d%s", getuid(), plname);
  244.         getlock();    /* sets lock if locknum != 0 */
  245. #ifdef WIZARD
  246.     } else
  247.         Sprintf(lock, "%d%s", getuid(), plname);
  248. #endif /* WIZARD /**/
  249.     setftty();
  250.  
  251.     /*
  252.      * Initialisation of the boundaries of the mazes
  253.      * Both boundaries have to be even.
  254.      */
  255.  
  256.     x_maze_max = COLNO-1;
  257.     if (x_maze_max % 2)
  258.         x_maze_max--;
  259.     y_maze_max = ROWNO-1;
  260.     if (y_maze_max % 2)
  261.         y_maze_max--;
  262.  
  263.     /* initialize static monster strength array */
  264.     init_monstr();
  265.  
  266.     Sprintf(SAVEF, "save/%d%s", getuid(), plname);
  267.     regularize(SAVEF+5);        /* avoid . or / in name */
  268. #ifdef COMPRESS
  269.     Strcpy(old,SAVEF);
  270.     Strcat(SAVEF,".Z");
  271.     if((fd = open(SAVEF,O_RDONLY)) >= 0) {
  272.          (void) close(fd);
  273.         Strcpy(cmd, COMPRESS);
  274.         Strcat(cmd, " -d ");    /* uncompress */
  275. # ifdef COMPRESS_OPTIONS
  276.         Strcat(cmd, COMPRESS_OPTIONS);
  277.         Strcat(cmd, " ");
  278. # endif
  279.         Strcat(cmd,SAVEF);
  280.         (void) system(cmd);
  281.     }
  282.     Strcpy(SAVEF,old);
  283. #endif
  284.     if((fd = open(SAVEF,O_RDONLY)) >= 0 &&
  285.        /* if not up-to-date, quietly unlink file via false condition */
  286.        (uptodate(fd) || unlink(SAVEF) == 666)) {
  287. #ifdef WIZARD
  288.         /* Since wizard is actually flags.debug, restoring might
  289.          * overwrite it.
  290.          */
  291.         boolean remember_wiz_mode = wizard;
  292. #endif
  293.         (void) chmod(SAVEF,0);    /* disallow parallel restores */
  294.         (void) signal(SIGINT, (SIG_RET_TYPE) done1);
  295.         pline("Restoring save file...");
  296.         (void) fflush(stdout);
  297.         if(!dorecover(fd))
  298.             goto not_recovered;
  299. #ifdef WIZARD
  300.         if(!wizard && remember_wiz_mode) wizard = TRUE;
  301. #endif
  302.         pline("Hello %s, welcome to NetHack!", plname);
  303.         /* get shopkeeper set properly if restore is in shop */
  304.         (void) inshop();
  305. #ifdef EXPLORE_MODE
  306.         if (discover)
  307.             You("are in non-scoring discovery mode.");
  308. #endif
  309. #if defined(EXPLORE_MODE) || defined(WIZARD)
  310.         if (discover || wizard) {
  311.             pline("Do you want to keep the save file? ");
  312.             if(yn() == 'n')
  313.                 (void) unlink(SAVEF);
  314.             else {
  315.                 (void) chmod(SAVEF,FCMASK); /* back to readable */
  316. # ifdef COMPRESS
  317.                 Strcpy(cmd, COMPRESS);
  318.                 Strcat(cmd, " ");
  319. #  ifdef COMPRESS_OPTIONS
  320.                 Strcat(cmd, COMPRESS_OPTIONS);
  321.                 Strcat(cmd, " ");
  322. #  endif
  323.                 Strcat(cmd,SAVEF);
  324.                 (void) system(cmd);
  325. # endif
  326.             }
  327.         }
  328. #endif
  329.         flags.move = 0;
  330.     } else {
  331. not_recovered:
  332.         newgame();
  333.         /* give welcome message before pickup messages */
  334.         pline("Hello %s, welcome to NetHack!", plname);
  335. #ifdef EXPLORE_MODE
  336.         if (discover)
  337.             You("are in non-scoring discovery mode.");
  338. #endif
  339.         flags.move = 0;
  340.         set_wear();
  341.         pickup(1);
  342.         read_engr_at(u.ux,u.uy);
  343.     }
  344.  
  345.     flags.moonphase = phase_of_the_moon();
  346.     if(flags.moonphase == FULL_MOON) {
  347.         You("are lucky!  Full moon tonight.");
  348.         if(!u.uluck) change_luck(1);
  349.     } else if(flags.moonphase == NEW_MOON) {
  350.         pline("Be careful!  New moon tonight.");
  351.     }
  352.  
  353.     initrack();
  354.  
  355.     moveloop();
  356.     return(0);
  357. }
  358.  
  359. void
  360. glo(foo)
  361. register int foo;
  362. {
  363.     /* construct the string  xlock.n  */
  364.     register char *tf;
  365.  
  366.     tf = lock;
  367.     while(*tf && *tf != '.') tf++;
  368.     Sprintf(tf, ".%d", foo);
  369. }
  370.  
  371. /*
  372.  * plname is filled either by an option (-u Player  or  -uPlayer) or
  373.  * explicitly (by being the wizard) or by askname.
  374.  * It may still contain a suffix denoting pl_character.
  375.  */
  376. void
  377. askname() {
  378.     register int c, ct;
  379.  
  380.     Printf("\nWho are you? ");
  381.     (void) fflush(stdout);
  382.     ct = 0;
  383.     while((c = Getchar()) != '\n') {
  384.         if(c == EOF) error("End of input\n");
  385.         /* some people get confused when their erase char is not ^H */
  386.         if(c == '\010') {
  387.             if(ct) ct--;
  388.             continue;
  389.         }
  390.         if(c != '-')
  391.         if(c < 'A' || (c > 'Z' && c < 'a') || c > 'z') c = '_';
  392.         if(ct < sizeof(plname)-1)
  393.             plname[ct++] = c;
  394.     }
  395.     plname[ct] = 0;
  396.     if(ct == 0) askname();
  397. }
  398.  
  399. #ifdef CHDIR
  400. static void
  401. chdirx(dir, wr)
  402. char *dir;
  403. boolean wr;
  404. {
  405.  
  406. # ifdef SECURE
  407.     if(dir                    /* User specified directory? */
  408. #  ifdef HACKDIR
  409.            && strcmp(dir, HACKDIR)        /* and not the default? */
  410. #  endif
  411.         ) {
  412.         (void) setgid(getgid());
  413.         (void) setuid(getuid());        /* Ron Wessels */
  414.     }
  415. # endif
  416.  
  417. # ifdef HACKDIR
  418.     if(dir == NULL)
  419.         dir = HACKDIR;
  420. # endif
  421.  
  422.     if(dir && chdir(dir) < 0) {
  423.         perror(dir);
  424.         error("Cannot chdir to %s.", dir);
  425.     }
  426.  
  427.     /* warn the player if we can't write the record file */
  428.     /* perhaps we should also test whether . is writable */
  429.     /* unfortunately the access systemcall is worthless */
  430.     if(wr) {
  431.         register int fd;
  432.  
  433.         if(dir == NULL)
  434.         dir = ".";
  435.         if((fd = open(RECORD, O_RDWR)) < 0) {
  436.         if((fd = open(RECORD, O_CREAT|O_RDWR, FCMASK)) < 0) {
  437.             Printf("Warning: cannot write %s/%s", dir, RECORD);
  438.             getret();
  439.         } else
  440.             (void) close(fd);
  441.         } else
  442.         (void) close(fd);
  443.     }
  444. }
  445. #endif /* CHDIR /**/
  446.  
  447. static void
  448. whoami() {
  449.     /*
  450.      * Who am i? Algorithm: 1. Use name as specified in NETHACKOPTIONS
  451.      *            2. Use $USER or $LOGNAME    (if 1. fails)
  452.      *            3. Use getlogin()        (if 2. fails)
  453.      * The resulting name is overridden by command line options.
  454.      * If everything fails, or if the resulting name is some generic
  455.      * account like "games", "play", "player", "hack" then eventually
  456.      * we'll ask him.
  457.      * Note that we trust the user here; it is possible to play under
  458.      * somebody else's name.
  459.      */
  460.     register char *s;
  461.  
  462.     if(!*plname && (s = getenv("USER")))
  463.         (void) strncpy(plname, s, sizeof(plname)-1);
  464.     if(!*plname && (s = getenv("LOGNAME")))
  465.         (void) strncpy(plname, s, sizeof(plname)-1);
  466.     if(!*plname && (s = getlogin()))
  467.         (void) strncpy(plname, s, sizeof(plname)-1);
  468. }
  469.